package com.chunfeng.service.impl;

import com.chunfeng.config.AvatarConfig;
import com.chunfeng.entity.Address;
import com.chunfeng.entity.Role;
import com.chunfeng.entity.User;
import com.chunfeng.mapper.AddressMapper;
import com.chunfeng.mapper.RoleMapper;
import com.chunfeng.mapper.UserMapper;
import com.chunfeng.result.JsonRequest;
import com.chunfeng.result.ServiceEnum;
import com.chunfeng.service.IUserService;
import com.chunfeng.utils.PasswordEncoderUtils;
import com.chunfeng.utils.RedisClientsUtils;
import com.chunfeng.utils.SqlDateUtils;
import com.chunfeng.utils.TokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * 用户业务层实现类
 *
 * @author by 春风能解释
 * <p>
 * 2022/12/19
 */
@Service
@Slf4j
@Transactional
public class UserServiceImpl implements IUserService {
    /**
     * 获取当前时间
     */
    private final String date = SqlDateUtils.date;
    /**
     * 用户mapper注入
     */
    @Autowired
    private UserMapper userMapper;
    /**
     * 角色Mapper注入
     */
    @Autowired
    private RoleMapper roleMapper;
    /**
     * 地址Mapper注入
     */
    @Autowired
    private AddressMapper addressMapper;
    /**
     * redis客户端注入
     */
    @Autowired
    private RedisClientsUtils redisClientsUtils;
    /**
     * 密码加密注入
     */
    @Autowired
    private PasswordEncoderUtils passwordEncoderUtils;
    /**
     * 文件配置
     */
    @Autowired
    private AvatarConfig avatarConfig;

    /**
     * 用户登录
     *
     * @param username 用户名
     * @param password 密码
     * @return JSON
     */
    @Override
    public JsonRequest<String> login(String username, String password) {
        //判断用户信息是否存在
        User user = userMapper.selectAllByName(username);
        if (Objects.isNull(user) || user.getStatus() != 0) {
            log.warn("名为{}的用户不存在!", username);
            return JsonRequest.error(ServiceEnum.NOT_FOUND);
        }
        //加密密码并检验
        if (!passwordEncoderUtils.check(password, user.getPassword())) {
            log.error("用户密码错误!");
            return JsonRequest.error(ServiceEnum.LOGIN_ERROR);
        }
        //创建token
        String token = TokenUtils.createToken(user.getId());
        //将用户Id存入Redis
        redisClientsUtils.set(token, user.getId().toString());
        log.info("名为{}的用户登录成功!", username);
        return JsonRequest.success(token);
    }

    /**
     * 注册
     *
     * @param username 用户名
     * @param password 密码
     * @return JSON
     */
    @Override
    @CacheEvict(value = "user", allEntries = true)
    public JsonRequest<Integer> register(String username, String password) {
        User userByName = userMapper.selectAllByName(username);
        //判断用户是否已经存在
        if (Objects.nonNull(userByName)) {
            log.warn("名为{}的用户已在数据库中找到!", username);
            return JsonRequest.error(ServiceEnum.REGISTER_ERROR);
        }
        User user = new User();
        user.setName(username);
        user.setPassword(passwordEncoderUtils.encode(password));
        //自动插入
        user.setCreateUser(0);
        user.setCreateTime(date);
        //添加逻辑
        Integer column = userMapper.insertUser(user);
        if (column < 1) {
            log.error("名为{}的用户注册失败!", username);
            return JsonRequest.error(ServiceEnum.REGISTER_ERROR);
        }
        log.info("名为{}的用户注册成功!", username);
        return JsonRequest.success(column);
    }


    /**
     * 查看所有用户
     *
     * @return JSON
     */
    @Override
    @Cacheable(value = "user")
    public JsonRequest<List<User>> lookAllUser() {
        List<User> users = userMapper.selectAllUser();
        if (users.isEmpty()) {
            log.warn("没有找到任何数据!");
            return JsonRequest.error(ServiceEnum.NOT_FOUND);
        }
        log.info("已查询到{}条用户信息", users.size());
        return JsonRequest.success(users);
    }


    /**
     * 查看当前用户
     *
     * @param userId 用户Id
     * @return JSON
     */
    @Override
    @Cacheable(value = "user", key = "#userId")
    public JsonRequest<User> lookCurrentUser(Integer userId) {
        User user = userMapper.selectUserById(userId);
        if (Objects.isNull(user)) {
            log.warn("Id为{}的用户不存在!", userId);
            return JsonRequest.error(ServiceEnum.NOT_FOUND);
        }
        //存入权限信息,方便前端处理
        Role role = roleMapper.selectAllRoleById(user.getRole());
        //获取地址信息
        if (user.getAddress() != null) {
            Address address = addressMapper.selectAllAddressById(user.getAddress());
            user.setPermissions(role.getPermissions());
            StringBuilder addressInfo = new StringBuilder();
            //将地址转换成需要的格式:
            //xxx学校 xx楼 x栋 x层 x号
            addressInfo
                    .append(address.getSchoolName())
                    .append(address.getFloor())
                    .append(address.getRidgepole())
                    .append("栋")
                    .append(address.getLayer())
                    .append("层")
                    .append(address.getNumber())
                    .append("号");
            user.setAddressInfo(addressInfo.toString());
        }
        log.info("已查询到Id为{}的用户!", userId);
        return JsonRequest.success(user);
    }

    /**
     * 根据角色查询用户
     *
     * @param role 角色ID
     * @return JSON
     */
    @Override
    public JsonRequest<List<User>> lookUserByRole(Integer role) {
        List<User> users = userMapper.selectAllByRole(role);
        if (users.isEmpty()) {
            log.warn("没有找到任何数据!");
            return JsonRequest.error(ServiceEnum.NOT_FOUND);
        }
        log.info("已查询到{}条用户信息", users.size());
        return JsonRequest.success(users);
    }

    /**
     * 修改当前用户信息
     *
     * @param user 用户信息
     * @return JSON
     */
    @Override
    @CacheEvict(value = "user", allEntries = true)
    public JsonRequest<Integer> updateCurrentUser(User user) {
        User selectUserById = userMapper.selectUserById(user.getId());
        if (Objects.isNull(selectUserById)) {
            log.warn("没有查询到Id为{}的用户!", user.getId());
            return JsonRequest.error(ServiceEnum.NOT_FOUND);
        }
        //判断密码字段是否存在
        if (user.getPassword() != null) {
            //密码加密处理
            user.setPassword(passwordEncoderUtils.encode(user.getPassword()));
        }
        //填充
        user.setUpdateUser(SqlDateUtils.currentUserId);
        user.setUpdateTime(date);
        Integer column = userMapper.updateUserById(user);
        if (column < 1) {
            log.error("Id为{}的用户修改失败!返回值{}", user.getId(), column);
            return JsonRequest.error(ServiceEnum.UPDATE_ERROR);
        }
        log.info("Id为{}的用户修改成功!返回值{}", user.getId(), column);
        return JsonRequest.success(column);
    }

    /**
     * 批量删除用户
     *
     * @param userIds 用户Id
     * @return JSON
     */
    @Override
    @CacheEvict(value = "user", allEntries = true)
    public JsonRequest<Integer> deleteUsers(Integer[] userIds) {
        //判断用户信息是否完整
        Integer count = userMapper.countUser(userIds);
        if (count < userIds.length) {
            log.warn("待删除的用户个数与数据库已存在的用户个数不符!数据库实际存在{}个,需要{}个", count, userIds.length);
            return JsonRequest.error(ServiceEnum.NOT_FOUND);
        }
        //获取redis中的用户信息
        String user = redisClientsUtils.get("user");
        //判断待删除的用户与已登陆用户是否一致
        for (Integer userId : userIds) {
            //判断该用户是否已登录
            if (userId.toString().equals(user)) {
                log.warn("Id为{}的用户已登陆!", user);
                return JsonRequest.error(ServiceEnum.DELETE_ERROR);
            }
        }
        //删除逻辑
        Integer column = userMapper.deleteUsersById(userIds);
        if (column < 1) {
            log.error("删除用户遇到错误!返回值{}", column);
            return JsonRequest.error(ServiceEnum.DELETE_ERROR);
        }
        log.info("已删除{}条用户信息!返回值{}", count, column);
        return JsonRequest.success(column);
    }

    /**
     * 用户头像上传
     *
     * @param file 文件流
     * @param id   ID值
     * @return JSON
     */
    @Override
    @CacheEvict(value = "user", allEntries = true)
    public JsonRequest<Integer> uploadAvatar(MultipartFile file, Integer id) {
        //检查文件大小
        if (file.getSize() > avatarConfig.getMaxSize() * 1024 * 1024) {
            return JsonRequest.error(ServiceEnum.UPLOAD_FILE_BEYOND_MAX_SIZE);
        }
        //获取用户信息
        User user = userMapper.selectUserById(id);
        if (Objects.isNull(user)) {
            log.warn("没有查询到Id为{}的用户!", id);
            return JsonRequest.error(ServiceEnum.NOT_FOUND);
        }
        //删除旧头像节省磁盘空间
        File oldAvatar = new File(user.getAvatar());
        if (oldAvatar.exists()) {
            boolean delete = oldAvatar.delete();
            if (!delete) {
                log.warn("文件删除失败!");
                return JsonRequest.error(ServiceEnum.UPLOAD_FILE_ERROR);
            }
        }
        //随机生成文件名
        String fileName = RandomStringUtils.randomNumeric(6) + ".png";
        //完整文件路径
        String URL = avatarConfig.getUrl() + fileName;
        try {
            //上传文件
            file.transferTo(new File(URL));
        } catch (IOException e) {
            log.error("文件上传失败!文件路径:{}", URL);
            return JsonRequest.error(ServiceEnum.UPLOAD_FILE_ERROR);
        }
        User user1 = new User();
        user1.setId(id);
        user1.setAvatar(URL);
        //填充
        user1.setUpdateUser(SqlDateUtils.currentUserId);
        user1.setUpdateTime(date);
        //修改用户信息
        Integer column = userMapper.updateUserById(user1);
        if (column < 1) {
            log.error("Id为{}的用户修改失败!返回值{}", id, column);
            return JsonRequest.error(ServiceEnum.UPDATE_ERROR);
        }
        log.info("Id为{}的用户头像上传成功!文件路径:{}", id, URL);
        return JsonRequest.success(column);
    }

    /**
     * 头像下载
     *
     * @param id ID值
     * @return 文件流
     */
    @Override
    public ResponseEntity downloadAvatar(Integer id) {
        ResourceLoader resourceLoader = new DefaultResourceLoader();
        User user = userMapper.selectUserById(id);
        if (Objects.isNull(user)) {
            log.warn("没有查询到Id为{}的用户!", id);
            return ResponseEntity.notFound().build();
        }
        //获取文件路径
        String avatar = user.getAvatar();
        if (avatar.equals("0")) {
            log.warn("用户ID为{}的头像未设置", user.getId());
            //设置一个空头像代替
            return ResponseEntity.ok(resourceLoader.getResource("file:" + avatarConfig.getUrl() + "null.png"));
        }
        try {
            log.info("已找到路径为[{}]的文件!", avatar);
            return ResponseEntity.ok(resourceLoader.getResource("file:" + avatar));
        } catch (Exception e) {
            log.warn("没有找到路径为[{}]的文件!", avatar);
            return ResponseEntity.notFound().build();
        }
    }
}
